/* 该程序是一个驱动程序，它创建了多个computethread线程，并允许它们在设置一个标志来结束计算前计算
 * 给定的秒数。然后，main程序调用程序13.8中的showresults函数获取共享的总和及累加值的数量。
 * showresults函数用于计算这些值的平均值。它还计算出在[0,1]范围内正弦函数的理论平均值，并给
 * 出平均值的踪误差和百分比误差。
 */
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "sharesum.h"
#include "globalerror.h"
#include "doneflag.h"
#include "computethread.h"

int showresults(void);

int main (int argc, char *argv[]) {
    int i, error, numthreads;
    int sleeptime;
    pthread_t *tids;

    /*在命令行中传递numthreads和sleeptime*/
    if (argc != 3) {
        fprintf(stderr, "Usage: %s numthreads sleeptime\n", argv[0]);
        return 1;
    }

    numthreads = atoi(argv[1]);
    sleeptime = atoi(argv[2]);

    // 开辟空间
    if (( tids = (pthread_t *)calloc(numthreads, sizeof(pthread_t)) ) == NULL) {
        fprintf(stderr, "Failed to calloc space for thread IDs");
        return 1;
    }

    /*创建numthreads个computethread线程*/
    for (i = 0; i < numthreads; ++i) {
        if (error = pthread_create(tids + i, NULL, computethread, NULL)) {
            fprintf(stderr, "Failed to start thread %d:%s\n", i, strerror(error));
            return 1;
        }
    }

    sleep(sleeptime);

    /*告诉computethread结束*/
    if (error = setdone()) {
        fprintf(stderr, "Failed to set done:%s\n", strerror(error));
        return 1;
    }

    /*等待它们完成*/
    for (i = 0; i < numthreads; ++i) {
        if (error = pthread_join(tids[i], NULL)) {
            fprintf(stderr, "Failed to join thread %d:%s\n", i, strerror(error));
            return 1;
        }
    }

    if (showresults()) {
        return 1;
    }

    return 0;
}


int showresults(void) {
    double average, calculated;
    int count, error, gerror;
    double err, perr, sum;

    /* 获取结果 */
    if ((error = getcountandsum(&count, &sum)) != 0 || (error = geterror(&gerror) != 0)) {
        fprintf(stderr, "Failed to get results: %s\n", strerror(error));
        return -1;
    }

    /* 在computethread计算中发生了错误 */
    if (gerror) {
        fprintf(stderr, "Failed to compute sum: %s\n", strerror(gerror));
        return -1;
    }

    if (count == 0) {
        printf("No values were summed.\n");
    } else {
        calculated = 1.0 - cos(1.0);
        average = sum/count;
        err = average - calculated;
        perr = 100.0 * err / calculated;

        printf("The sum is %f and the count is %d\n", sum, count);
        printf("The average is %f and error is %f or %f%%\n", average, err, perr);
    }
    return 0;
}
